//
//  AirMemPool.h
//  AirCpp
//
//  Created by Penghao on 14-3-14.
//  Copyright (c) 2014年 PengHao. All rights reserved.
//

#ifndef __AirCpp__AirMemPool__
#define __AirCpp__AirMemPool__

#include <iostream>
#include "AirObject.h"
#include "../AirContainer/AirArray.h"
namespace AirCpp{
    class AirMemBlock : public AirObject{
    public:
        char * p_block_data;
        unsigned long block_size;
    public:
        bool is_freed;
        AirMemBlock(){
            p_block_data = NULL;
            is_freed = true;
        }
        int init(char *data, unsigned long size){
            p_block_data = data;
            block_size = size;
            return 0;
        }
    };
    
    class AirMemPool : public AirObject{
    private:
        unsigned long total_size;
        unsigned long block_num;
        AirMutableArray<AirMemBlock> used_blocks;
    public:
        char * p_mem_block;
        AirMemPool(){
            p_mem_block = NULL;
        };
        
        int init(unsigned long total_size_){
            total_size = total_size_;
            p_mem_block = (char *)malloc(total_size_);
            if (p_mem_block == NULL) {
                return -1;
            }else{
                return 0;
            }
        };
        
        char * const apply(unsigned long size){
            char *p_tmp = p_mem_block;
            unsigned int i = 0;
            bool isfind = false;
            unsigned long num = used_blocks.count();
            if (num > 0) {
                for (i = 0; i < num&&!isfind; ++i) {
                    AirMemBlock *block = used_blocks[i];
                    if (block->p_block_data - p_tmp < size) {
                        p_tmp = block->p_block_data+block->block_size;
                    }else{
                        isfind = true;
                    }
                }
                isfind = isfind?true:i == num && (total_size - (p_tmp - p_mem_block) >= size);
            }else{
                isfind = (total_size >= size);
            }

            if (isfind) {
                AirMemBlock *p_block = new AirMemBlock();
                p_block->init(p_tmp, size);
                num == 0 ? used_blocks.add_object(p_block) : used_blocks.insert_object(p_block, i-1);
                return p_block->p_block_data;
            }else{
                return NULL;
            }
        }
        
        int revert(char *p_mem){
            for (int i = 0; i < used_blocks.count(); ++i) {
                if( p_mem == used_blocks[i]->p_block_data){
                    //find it！
                    if (used_blocks[i]->retain_count>1) {
                        release(used_blocks[i]);
                    }else{
                        used_blocks.remove_object_at_index(i);
                    }
                    return 0;
                }
            }
            return -1;
        }
        
        char * quote(char *p_mem){
            for (int i = 0; i < used_blocks.count(); ++i) {
                if( p_mem == used_blocks[i]->p_block_data){
                    //find it！
                    retain(used_blocks[i]);
                    return p_mem;
                }
            }
            return NULL;
        }
        
    };
}
#endif /* defined(__AirCpp__AirMemPool__) */
